From 1946c447cb991b396391d04e092be68f2f03f515 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 10 Jul 2014 16:03:01 -0700 Subject: [PATCH] Add bare-bones cross compilation support to cargo This adds a new flag, --target, to the `cargo-build` command. This flag will indicate that all output should be scoped under the `$triple` directory inside of the output `target` directory. The compiler is invoked with `--target $triple` and all custom build commands are passed `TRIPLE` if one is provided. --- src/bin/cargo-build.rs | 4 +++- src/bin/cargo-git-checkout.rs | 2 +- src/bin/cargo-test.rs | 3 ++- src/cargo/ops/cargo_compile.rs | 10 ++++++---- src/cargo/ops/cargo_rustc.rs | 16 +++++++++++++--- src/cargo/util/config.rs | 11 +++++++++-- 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/bin/cargo-build.rs b/src/bin/cargo-build.rs index d0530615c..9e4ef547e 100644 --- a/src/bin/cargo-build.rs +++ b/src/bin/cargo-build.rs @@ -24,6 +24,7 @@ pub struct Options { manifest_path: Option, update_remotes: bool, jobs: Option, + target: Option, release: bool, } @@ -59,7 +60,8 @@ fn execute(options: Options, shell: &mut MultiShell) -> CliResult> { update: options.update_remotes, env: env, shell: shell, - jobs: options.jobs + jobs: options.jobs, + target: options.target.as_ref().map(|t| t.as_slice()), }; ops::compile(&root, opts).map(|_| None).map_err(|err| { diff --git a/src/bin/cargo-git-checkout.rs b/src/bin/cargo-git-checkout.rs index d0d4a920c..3e1d601f7 100644 --- a/src/bin/cargo-git-checkout.rs +++ b/src/bin/cargo-git-checkout.rs @@ -37,7 +37,7 @@ fn execute(options: Options, shell: &mut MultiShell) -> CliResult> { let source_id = SourceId::for_git(&url, reference.as_slice()); - let mut config = try!(Config::new(shell, true, None).map_err(|e| { + let mut config = try!(Config::new(shell, true, None, None).map_err(|e| { CliError::from_boxed(e, 1) })); let mut source = GitSource::new(&source_id, &mut config); diff --git a/src/bin/cargo-test.rs b/src/bin/cargo-test.rs index 1967c59fd..b0e2a41a4 100644 --- a/src/bin/cargo-test.rs +++ b/src/bin/cargo-test.rs @@ -49,7 +49,8 @@ fn execute(options: Options, shell: &mut MultiShell) -> CliResult> { update: options.update, env: "test", shell: shell, - jobs: options.jobs + jobs: options.jobs, + target: None, }; try!(ops::compile(&root, compile_opts).map(|_| None::<()>).map_err(|err| { diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 340ff4c26..427616b9d 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -34,11 +34,13 @@ pub struct CompileOptions<'a> { pub update: bool, pub env: &'a str, pub shell: &'a mut MultiShell, - pub jobs: Option + pub jobs: Option, + pub target: Option<&'a str>, } pub fn compile(manifest_path: &Path, options: CompileOptions) -> CargoResult<()> { - let CompileOptions { update, env, shell, jobs } = options; + let CompileOptions { update, env, shell, jobs, target } = options; + let target = target.map(|s| s.to_string()); log!(4, "compile; manifest-path={}", manifest_path.display()); @@ -58,7 +60,7 @@ pub fn compile(manifest_path: &Path, options: CompileOptions) -> CargoResult<()> let source_ids = package.get_source_ids(); let (packages, resolve) = { - let mut config = try!(Config::new(shell, update, jobs)); + let mut config = try!(Config::new(shell, update, jobs, target.clone())); let mut registry = try!(PackageRegistry::new(source_ids, override_ids, &mut config)); @@ -81,7 +83,7 @@ pub fn compile(manifest_path: &Path, options: CompileOptions) -> CargoResult<()> target.get_profile().get_env() == env }).collect::>(); - let mut config = try!(Config::new(shell, update, jobs)); + let mut config = try!(Config::new(shell, update, jobs, target)); try!(ops::compile_targets(env.as_slice(), targets.as_slice(), &package, &PackageSet::new(packages.as_slice()), &resolve, &mut config)); diff --git a/src/cargo/ops/cargo_rustc.rs b/src/cargo/ops/cargo_rustc.rs index d8be4f11a..378efd902 100644 --- a/src/cargo/ops/cargo_rustc.rs +++ b/src/cargo/ops/cargo_rustc.rs @@ -54,8 +54,9 @@ pub fn compile_targets<'a>(env: &str, targets: &[&Target], pkg: &Package, debug!("compile_targets; targets={}; pkg={}; deps={}", targets, pkg, deps); - let path_fragment = uniq_target_dest(targets); - let target_dir = pkg.get_absolute_target_dir().join(path_fragment.unwrap_or("")); + let target_dir = pkg.get_absolute_target_dir() + .join(config.target().unwrap_or("")) + .join(uniq_target_dest(targets).unwrap_or("")); let deps_target_dir = target_dir.join("deps"); let output = try!(util::process("rustc").arg("-v").exec_with_output()); @@ -223,7 +224,8 @@ fn compile_custom(pkg: &Package, cmd: &str, .cwd(pkg.get_root()) .env("OUT_DIR", Some(cx.dest.as_str().expect("non-UTF8 dest path"))) .env("DEPS_DIR", Some(cx.dest.join(cx.deps_dir) - .as_str().expect("non-UTF8 deps path"))); + .as_str().expect("non-UTF8 deps path"))) + .env("TARGET", cx.config.target()); for arg in cmd { p = p.arg(arg); } @@ -326,6 +328,14 @@ fn build_base_args(into: &mut Args, into.push("-o".to_string()); into.push(out.join(target.get_name()).display().to_string()); } + + match cx.config.target() { + Some(target) => { + into.push("--target".to_string()); + into.push(target.to_string()); + } + None => {} + } } fn build_deps_args(dst: &mut Args, package: &Package, cx: &Context) { diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index de48b375d..1745ae1ce 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -12,12 +12,14 @@ pub struct Config<'a> { update_remotes: bool, shell: &'a mut MultiShell, jobs: uint, + target: Option, } impl<'a> Config<'a> { pub fn new<'a>(shell: &'a mut MultiShell, update_remotes: bool, - jobs: Option) -> CargoResult> { + jobs: Option, + target: Option) -> CargoResult> { if jobs == Some(0) { return Err(human("jobs must be at least 1")) } @@ -29,6 +31,7 @@ impl<'a> Config<'a> { update_remotes: update_remotes, shell: shell, jobs: jobs.unwrap_or(os::num_cpus()), + target: target, }) } @@ -48,9 +51,13 @@ impl<'a> Config<'a> { self.update_remotes } - pub fn jobs(&mut self) -> uint { + pub fn jobs(&self) -> uint { self.jobs } + + pub fn target<'a>(&'a self) -> Option<&'a str> { + self.target.as_ref().map(|t| t.as_slice()) + } } #[deriving(Eq,PartialEq,Clone,Encodable,Decodable)] -- 2.30.2